#include "seqiot.h"
#include "model.h"
#include "sqlite.h"
#include "bcd.h"

#define SQL_DEVICE_COLS "id,name,type,channel,slave_id,shift_idx,meter_addr,u0,i0,ubb,ibb,u_decimal,i_decimal,p_decimal,device_key,device_secret"

device_t *device_new() {
    device_t *device = z_calloc(1, sizeof(device_t));
    device->values = hash_new(32, &int_hash_ops);
    return device;
}

void device_free(device_t *device) {
    if (!device) return;

    hash_delete(device->values);

    if (0 != device->shift_idx) {
        product_free(device->_product);
    }

    for (int i = 0; i < sizeof(device->thing_value) / sizeof(device->thing_value[0]); ++i) {
        vector_t *model = &device->thing_value[i];
        vector_foreach(model, (vector_foreach_callback) thing_model_free);
    }

    z_free(device);
}

void read_row_device(sqlite3_stmt *stmt, device_t *rs) {
    int idx = 2;
    read_row_object(stmt, &rs->super);

    rs->product = sqlite3_column_int(stmt, idx++);
    rs->channel = sqlite3_column_int(stmt, idx++);

    rs->slave_id = sqlite3_column_int(stmt, idx++);
    rs->shift_idx = sqlite3_column_int(stmt, idx++);
    write_unsigned_int64(rs->meter_addr, 12, sqlite3_column_int64(stmt, idx++));
    rs->u0 = sqlite3_column_int(stmt, idx++);
    rs->i0 = sqlite3_column_int(stmt, idx++);
    rs->ubb = sqlite3_column_int(stmt, idx++);
    rs->ibb = sqlite3_column_int(stmt, idx++);
    rs->u_decimal = sqlite3_column_int(stmt, idx++);
    rs->i_decimal = sqlite3_column_int(stmt, idx++);
    rs->p_decimal = sqlite3_column_int(stmt, idx++);

    read_row_str(stmt, idx++, rs->device_key, sizeof(rs->device_key));
    read_row_str(stmt, idx++, rs->device_secret, sizeof(rs->device_secret));

}

int read_stmt_devices(sqlite3 *db, vector_t *devices, obj_id channel) {
    int rc;
    sqlite3_stmt *stmt = NULL;
    char sql[1024];

    sprintf(sql, "SELECT %s FROM device WHERE channel=? AND %s", SQL_DEVICE_COLS, SQL_DISABLE);
    rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);
    if (SQLITE_OK != rc) {
        sqlite_check(db);
        goto err;
    }

    rc = sqlite3_bind_int(stmt, 1, channel);
    if (SQLITE_OK != rc) {
        sqlite_check(db);
        goto err;
    }

    while (SQLITE_ROW == sqlite3_step(stmt)) {
        device_t *device = device_new();
        read_row_device(stmt, device);
        vector_add(devices, device);
    }

    err:
    sqlite3_finalize(stmt);
    return rc;
}

int read_stmt_all_devices(sqlite3 *db, vector_t *devices) {
    int rc;
    sqlite3_stmt *stmt = NULL;
    char sql[1024];

    sprintf(sql, "SELECT %s FROM device WHERE %s", SQL_DEVICE_COLS, SQL_DISABLE);
    rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);
    if (SQLITE_OK != rc) {
        sqlite_check(db);
        goto err;
    }

    while (SQLITE_ROW == sqlite3_step(stmt)) {
        device_t *device = device_new();
        read_row_device(stmt, device);
        vector_add(devices, device);
    }

    err:
    sqlite3_finalize(stmt);
    return rc;
}